#include <iostream>
#include <vector>

// 元素接口：所有图形元素都应实现这个接口
class GraphicElement {
public:
    virtual ~GraphicElement() {}
    virtual void accept(class Visitor& v) = 0;  		// 接收访问者的方法
};

// 访问者接口
class Visitor {
public:
    virtual void visitCircle(class Circle& c) = 0;
    virtual void visitRectangle(class Rectangle& r) = 0;
    virtual void visitPolygon(class Polygon& p) = 0;
};

// 具体元素类：圆形
class Circle : public GraphicElement {
public:
    int radius = 5;  									// 圆的半径

    void accept(Visitor& v) override {
        v.visitCircle(*this);  							// 调用访问者的访问方法
    }
};

// 具体元素类：矩形
class Rectangle : public GraphicElement {
public:
    int width = 10;
    int height = 20;  								// 矩形的宽和高

    void accept(Visitor& v) override {
        v.visitRectangle(*this); 						// 调用访问者的访问方法
    }
};

// 具体元素类：多边形
class Polygon : public GraphicElement {
public:
    std::vector<std::pair<int, int>> points = {{0, 0}, {5, 10}, {10, 0}}; // 多边形的顶点

    void accept(Visitor& v) override {
        v.visitPolygon(*this);  						// 调用访问者的访问方法
    }
};

// 具体访问者：导出为SVG格式
class SVGExportVisitor : public Visitor {
public:
    void visitCircle(Circle& c) override {
        std::cout << "<svg><circle r='" << c.radius << "' /></svg>" << std::endl;  // SVG格式输出圆形
    }

    void visitRectangle(Rectangle& r) override {
        std::cout << "<svg><rect width='" << r.width << "' height='" << r.height << "' /></svg>" << std::endl;  									// SVG格式输出矩形
    }

    void visitPolygon(Polygon& p) override {
        std::cout << "<svg><polygon points='";
        for (auto& point : p.points) {
            std::cout << point.first << "," << point.second << " ";
        }
        std::cout << "'/></svg>" << std::endl;  			// SVG格式输出多边形
    }
};

// 主函数：使用访问者模式
int main() {
    std::vector<GraphicElement*> elements;  			// 图形元素集合
    elements.push_back(new Circle());
    elements.push_back(new Rectangle());
    elements.push_back(new Polygon());

    SVGExportVisitor exportVisitor;  					// 创建导出访问者

    // 遍历所有元素并接受访问
    for (GraphicElement* element : elements) {
        element->accept(exportVisitor);  				// 元素接收访问者，进行导出操作
    }

    // 清理资源
    for (GraphicElement* element : elements) {
        delete element;
    }
    elements.clear();

    return 0;
}